package io.renren.service.impl;

import io.renren.common.utils.ConfigConstant;
import io.renren.common.utils.DateUtils;
import io.renren.common.utils.DecimalUtils;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.ProjectConstant;
import io.renren.common.utils.Query;
import io.renren.common.utils.SMSManages;
import io.renren.common.validator.Assert;
import io.renren.dao.CtocTransactionDao;
import io.renren.entity.BalanceDetailEntity;
import io.renren.entity.CtocOrderEntity;
import io.renren.entity.CtocTransCountEntity;
import io.renren.entity.CtocTransactionEntity;
import io.renren.entity.MemberEntity;
import io.renren.service.BalanceDetailService;
import io.renren.service.CtocOrderService;
import io.renren.service.CtocTransCountService;
import io.renren.service.CtocTransactionService;
import io.renren.service.MemberService;
import io.renren.service.SysConfigService;

import java.util.Date;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;

@Service("ctocTransactionService")
public class CtocTransactionServiceImpl extends ServiceImpl<CtocTransactionDao, CtocTransactionEntity> implements CtocTransactionService {

	@Autowired
	CtocOrderService ctocOrderService;

	@Autowired
	MemberService memberService;

	@Autowired
	SysConfigService sysConfigService;

	@Autowired
	CtocTransCountService ctocTransCountService;

	@Autowired
	BalanceDetailService balanceDetailService;

	@Override
	public PageUtils queryPage(Map<String, Object> params) {
		EntityWrapper<CtocTransactionEntity> wrapper = new EntityWrapper<CtocTransactionEntity>();
		Long memberId = (Long) params.get("memberId");
		Integer status = (Integer) params.get("status");
		if (status == 1) {// 进行中的订单
			wrapper.in("status", new Integer[] { ProjectConstant.CTOC_TRANS_STATUS_NEEDPAY, ProjectConstant.CTOC_TRANS_STATUS_PAID });
		} else if (status == 2) {// 已完成的订单
			wrapper.eq("status", ProjectConstant.CTOC_TRANS_STATUS_CONFIRMED);
		} else if (status == 3) {// 取消的订单
			wrapper.eq("status", ProjectConstant.CTOC_TRANS_STATUS_CANCEL);
		}
		wrapper.andNew().eq("buyer_member_id", memberId).or().eq("seller_member_id", memberId);

		Page<CtocTransactionEntity> page = this.selectPage(new Query<CtocTransactionEntity>(params).getPage(), wrapper);

		return new PageUtils(page);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void sell(MemberEntity seller, Long orderId) {

		CtocOrderEntity ctocOrder = ctocOrderService.selectById(orderId);
		Assert.notNull(ctocOrder, "订单不存在");
		Assert.isTrue(ctocOrder.getStatus() == ProjectConstant.CTOC_ORDER_STATUS_SUBMIT, "订单已被其他人成交");
		Assert.isTrue(!ctocOrder.getMemberId().equals(seller.getId()), "订单不允许卖给自己");
		double transFee = sysConfigService.getValueD(ConfigConstant.TRANS_FEE);// 交易手续费率
		Assert.isTrue(transFee >= 0, "交易手续费设置错误,请联系客服");
		transFee = DecimalUtils.mul(ctocOrder.getCoinQuantity(), transFee);// 需要的AIC费用
		double needPayCoin = DecimalUtils.add(ctocOrder.getCoinQuantity(), transFee);
		Assert.isTrue(seller.getBalance() >= needPayCoin, "您的可用余额不足");

		Date now = new Date();

		// 更新挂单状态
		ctocOrder.setStatus(ProjectConstant.CTOC_ORDER_STATUS_TRADING);
		ctocOrder.setUpdateTime(now);
		ctocOrderService.updateById(ctocOrder);

		// 卖家账户余额冻结
		seller.setBalance(DecimalUtils.sub(seller.getBalance(), needPayCoin));
		seller.setBlockedBalance(DecimalUtils.add(seller.getBlockedBalance(), needPayCoin));
		seller.setUpdateTime(now);
		memberService.updateById(seller);

		// 买家信息
		MemberEntity buyer = memberService.selectById(ctocOrder.getMemberId());

		// 创建交易
		CtocTransactionEntity ctocTransaction = new CtocTransactionEntity();
		ctocTransaction.setOrderNo(ctocOrder.getOrderNo());
		ctocTransaction.setCoinPrice(ctocOrder.getCoinPrice());
		ctocTransaction.setCoinTotalPrice(ctocOrder.getCoinTotalPrice());
		ctocTransaction.setCoinQuantity(ctocOrder.getCoinQuantity());
		ctocTransaction.setBuyerMemberId(buyer.getId());
		ctocTransaction.setBuyerRealname(buyer.getRealname());
		ctocTransaction.setBuyerMobile(buyer.getMobile());
		ctocTransaction.setBuyerAlipay(buyer.getAlipay());
		ctocTransaction.setBuyerAlipayImg(buyer.getAlipayImg());
		ctocTransaction.setBuyerWechat(buyer.getWechat());
		ctocTransaction.setBuyerWechatImg(buyer.getWechatImg());
		ctocTransaction.setBuyerBankName(buyer.getBankName());
		ctocTransaction.setBuyerBankNameBranch(buyer.getBankNameBranch());
		ctocTransaction.setBuyerBankCardNumber(buyer.getBankCardNumber());
		ctocTransaction.setSellerMemberId(seller.getId());
		ctocTransaction.setSellerRealname(seller.getRealname());
		ctocTransaction.setSellerMobile(seller.getMobile());
		ctocTransaction.setSellerAlipay(seller.getAlipay());
		ctocTransaction.setSellerAlipayImg(seller.getAlipayImg());
		ctocTransaction.setSellerWechat(seller.getWechat());
		ctocTransaction.setSellerWechatImg(seller.getWechatImg());
		ctocTransaction.setSellerBankName(seller.getBankName());
		ctocTransaction.setSellerBankNameBranch(seller.getBankNameBranch());
		ctocTransaction.setSellerBankCardNumber(seller.getBankCardNumber());
		ctocTransaction.setStatus(ProjectConstant.CTOC_TRANS_STATUS_NEEDPAY);// 等待买家付款
		ctocTransaction.setTransFee(transFee);
		ctocTransaction.setCreateTime(now);
		this.insert(ctocTransaction);

		// 短信通知买家
		SMSManages sms = new SMSManages(sysConfigService.getValue(ConfigConstant.SMS_USER), sysConfigService.getValue(ConfigConstant.SMS_PWD),
				sysConfigService.getValue(ConfigConstant.SMS_VERY_CODE));
		String retCode = sms.sendSMS(buyer.getMobile(), "JSM42425-0003", "@1@=" + ctocOrder.getOrderNo());
		System.out.println("sell retCode：" + retCode);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancelTrans(MemberEntity buyer, Long transId) {

		CtocTransactionEntity ctocTransaction = this.selectById(transId);
		Assert.notNull(ctocTransaction, "交易ID不存在");
		Assert.isTrue(ctocTransaction.getBuyerMemberId().equals(buyer.getId()), "取消交易失败");
		Assert.isTrue(ctocTransaction.getStatus() == ProjectConstant.CTOC_TRANS_STATUS_NEEDPAY, "当前交易状态不允许取消");

		Date now = new Date();

		// 设置挂单为正常状态
		CtocOrderEntity ctocOrder = ctocOrderService.selectOne(new EntityWrapper<CtocOrderEntity>().eq("order_no", ctocTransaction.getOrderNo()));
		ctocOrder.setStatus(ProjectConstant.CTOC_ORDER_STATUS_SUBMIT);
		ctocOrder.setUpdateTime(now);
		ctocOrderService.updateById(ctocOrder);

		// 卖家账户余额解冻
		MemberEntity seller = memberService.selectById(ctocTransaction.getSellerMemberId());
		double blocked = DecimalUtils.add(ctocTransaction.getCoinQuantity(), ctocTransaction.getTransFee());// 解冻金额=总币+手续费
		seller.setBalance(DecimalUtils.add(blocked, seller.getBalance()));// 余额+解冻金额
		seller.setBlockedBalance(DecimalUtils.sub(seller.getBlockedBalance(), blocked));// 冻结金额-解冻金额
		seller.setUpdateTime(now);
		memberService.updateById(seller);

		// 交易取消
		ctocTransaction.setStatus(ProjectConstant.CTOC_TRANS_STATUS_CANCEL);
		ctocTransaction.setUpdateTime(now);
		ctocTransaction.setFinishTime(now);
		this.updateById(ctocTransaction);

		// 记录当日订单取消次数+1
		CtocTransCountEntity entity = ctocTransCountService.selectOne(new EntityWrapper<CtocTransCountEntity>().eq("member_id", buyer.getId()).ge("create_time",
				DateUtils.getStartOfDay(now)));
		if (entity == null) {
			entity = new CtocTransCountEntity();
			entity.setOrderCancel(1);
			entity.setCreateTime(now);
			ctocTransCountService.insert(entity);
		} else {
			entity.setOrderCancel(entity.getOrderCancel() + 1);
			entity.setUpdateTime(now);
			ctocTransCountService.updateById(entity);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void sellerConfirm(MemberEntity seller, Long transId) {

		CtocTransactionEntity ctocTransaction = this.selectById(transId);
		Assert.notNull(ctocTransaction, "交易不存在");
		Assert.isTrue(ctocTransaction.getSellerMemberId().equals(seller.getId()), "此订单您无法确认");
		Assert.isTrue(ctocTransaction.getStatus() == ProjectConstant.CTOC_TRANS_STATUS_PAID, "当前交易状态不可确认收款");

		Date now = new Date();

		// 更新会员余额
		double blocked = DecimalUtils.add(ctocTransaction.getCoinQuantity(), ctocTransaction.getTransFee());// 总币+手续费
		seller.setBlockedBalance(DecimalUtils.sub(seller.getBlockedBalance(), blocked));
		seller.setUpdateTime(now);
		memberService.updateById(seller);
		MemberEntity buyer = memberService.selectById(ctocTransaction.getBuyerMemberId());
		buyer.setBalance(DecimalUtils.add(buyer.getBalance(), ctocTransaction.getCoinQuantity()));// 余额+买入的币
		buyer.setUpdateTime(now);
		memberService.updateById(buyer);

		// 插入卖家资金流水
		BalanceDetailEntity bd = new BalanceDetailEntity();
		bd.setBalanceChange(DecimalUtils.sub(0, blocked));
		bd.setMemberId(seller.getId());
		bd.setCategory(1);// 卖出
		bd.setCreateTime(now);
		balanceDetailService.insert(bd);

		// 插入买家资金流水
		bd = new BalanceDetailEntity();
		bd.setBalanceChange(ctocTransaction.getCoinQuantity().doubleValue());
		bd.setMemberId(buyer.getId());
		bd.setCategory(0);// 买入
		bd.setCreateTime(now);
		balanceDetailService.insert(bd);

		// 更新挂单状态
		CtocOrderEntity ctocOrder = ctocOrderService.selectOne(new EntityWrapper<CtocOrderEntity>().eq("member_id", ctocTransaction.getBuyerMemberId()).eq("order_no",
				ctocTransaction.getOrderNo()));
		ctocOrder.setUpdateTime(now);
		ctocOrder.setStatus(ProjectConstant.CTOC_ORDER_STATUS_FINISH);
		ctocOrderService.updateById(ctocOrder);

		// 更新订单状态
		ctocTransaction.setUpdateTime(now);
		ctocTransaction.setFinishTime(now);
		ctocTransaction.setStatus(ProjectConstant.CTOC_TRANS_STATUS_CONFIRMED);
		this.updateById(ctocTransaction);
	}
}
